/*
 * lwipGvcp.h
 *
 *  Copyright (C) 2022-2024 BOQ Inc. All rights reserved.
 *
 *  Created on: 2024年3月29日
 *      Author: fitch
 */

#ifndef SRC_LWIPGVCP_H_
#define SRC_LWIPGVCP_H_

#include "stdbool.h"

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;

typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;

#define GIGE_MIN(x , y)  (((x) < (y)) ? (x) : (y))
#define SW_VERSION       "2.2.0"
#ifdef __cplusplus
extern "C" {
#endif

#define GVCP_DEV_NAME   "eth0"
#define GVCP_UDP_PORT   3956
#define GVCP_MIN_SIZE   8
#define GVCP_KEY_CODE   0x42
#define GVCP_REG_SIZE   N2000
#define GVCP_DEF_TIME   3000

/* GVCP support command and acknownedge */
#define GVCP_DISCOVERY_CMD	  2
#define GVCP_DISCOVERY_ACK	  3
#define GVCP_FORCEIP_CMD	  4
#define GVCP_FORCEIP_ACK	  5
#define GVCP_PACKETRESEND_CMD 0x40
#define GVCP_READREG_CMD	  0x80
#define GVCP_READREG_ACK	  0x81
#define GVCP_WRITEREG_CMD	  0x82
#define GVCP_WRITEREG_ACK	  0x83
#define GVCP_READMEM_CMD	  0x84
#define GVCP_READMEM_ACK	  0x85
#define GVCP_WRITEMEM_CMD     0x86
#define GVCP_WRITEMEM_ACK     0x87
#define GVCP_FORCEIP_BAS_CMD  0x8004
#define GVCP_FORCEIP_BAS_ACK  0x8005


/* GigE standard register */
#define REG_VER             0x0000
#define REG_DEV             0x0004 // Device mode
#define REG_MACH            0x0008
#define REG_MACL            0x000C
#define REG_CAIP            0x0010
#define REG_CGIP            0x0014
#define REG_CUIP            0x0024
#define REG_CSMK            0x0034
#define REG_CDGW            0x0044
#define REG_SNUM            0x00D8
#define REG_USID            0x00E8
#define REG_URL1            0x0200
#define REG_URL2            0x0400
#define REG_NONI            0x0600
#define REG_NOMC            0x0900
#define REG_NOSC            0x0904
#define REG_NOAS            0x0908
#define REG_SPCP            0x092C // GVSP Capability
#define REG_MSCP            0x0930
#define REG_CPCP            0x0934 // GVCP Capability
#define REG_HRTT            0x0938 // heartbeat timeout
#define REG_TTFH            0x093C
#define REG_TTFL            0x0940
#define REG_PDTT            0x0958 // Pending Timeout
#define REG_CCP             0x0A00 // Control Channel Privilege
#define REG_MCSP            0x0B00 // Message Channel Source Port
#define REG_MCDA            0x0B10 // Message Channel Destination Address
#define REG_MCTT            0x0B14 // Message Channel Transmission Timeout
#define REG_MCRC            0x0B18 // Message Channel Retry Count
#define REG_SCP0            0x0D00 // First Stream Channel Port register. remote port
#define REG_SCSP0           0x0D1C // source port. local port
#define REG_SCPS0           0x0D04 // stream ch0 packet size
#define REG_SCPD0           0x0D08 // Stream Channel Packet Delay
#define REG_SCDA0           0x0D18 // stream ch0 dest addr
#define REG_KEYID           0x4B45
#define MEM_SN              N947
#define MEM_TYPE            N948
/*GigE Custom register */
#define REG_CUST_BASE       0xA000
#define REG_CUST_SIZE       (GVCP_REG_SIZE - REG_CUST_BASE + 1)
#define REG_CCM_RR          N7
#define REG_CCM_MIN         N8
#define REG_CCM_MAX         N9
#define REG_CCM_COE         N10
#define REG_CCM_RG          N12
#define REG_CCM_RB          N14
#define REG_CCM_GR          N16
#define REG_CCM_GG          N18
#define REG_CCM_GB          N20
#define REG_CCM_BR          N22
#define REG_CCM_BG          N24
#define REG_CCM_BB          N26
#define REG_FLAT_CTL        N30
#define REG_FLAT_FPNC       N31
#define REG_FLAT_PRNUC      N32
#define REG_PRNUC_TGT_EN    N33
#define REG_PRNUC_TGT_VAL   N34
#define REG_PRNUC_TGT_MIN   N35
#define REG_PRNUC_TGT_MAX   N36
#define REG_PRNUC_TGT_INC   N37
#define REG_ENCODER_MODE    N50
#define REG_FREQ_DIV_VAL    N80
#define REG_FREQ_DIV_MIN    N81
#define REG_FREQ_DIV_MAX    N82
#define REG_FREQ_DIV_INC    N83
#define REG_CCM_EN          N276
#define REG_BLKL_VAL        N119
#define REG_BLKL_MIN        N120
#define REG_BLKL_MAX        N121
#define REG_GAMMA_CTL       N124
#define REG_GAMMA_VAL       N128
#define REG_GAMMA_MIN       N129
#define REG_GAMMA_MAX       N130
#define REG_GAMMA_SEL       N131
#define REG_DIGSHT_VAL      N136
#define REG_DIGSHT_MIN      N137
#define REG_DIGSHT_MAX      N138
#define REG_REVERSEX        N197
#define REG_REVERSEY        N199
#define REG_TDI_MODE        N200
#define REG_SEN_WIDTH       N216
#define REG_SEN_HEIGHT      N218
#define REG_SEN_TEMP        N219
#define REG_AOI_WIDTH       N336
#define REG_AOI_HEIGHT      N343
#define REG_AOI_XOFFSET     N350
#define REG_AOI_YOFFSET     N357
#define REG_AOI_XCENTER     N364
#define REG_AOI_YCENTER     N368
#define REG_BINMODEV_IMP    N370
#define REG_BINMODEV_VAL    N372
#define REG_BINVMODE_IMP    N1370
#define REG_BINVMODE_VAL    N1372
#define REG_BINMODEH_IMP    N374
#define REG_BINMODEH_VAL    N376
#define REG_BINHMODE_IMP    N1374
#define REG_BINHMODE_VAL    N1376
#define REG_BINNINGV_IMP    N377
#define REG_BINNINGV_VAL    N380
#define REG_BINNINGV_MIN    N381
#define REG_BINNINGV_MAX    N382
#define REG_BINNINGV_INC    N383
#define REG_BINNINGH_IMP    N384
#define REG_BINNINGH_VAL    N387
#define REG_BINNINGH_MIN    N388
#define REG_BINNINGH_MAX    N389
#define REG_BINNINGH_INC    N390
#define REG_ACQ_CTL         0xA198 // Acquisition control  (N408)
#define REG_ACQ_MOD         0xA199
#define REG_TRG_CTL         0xA19B
#define REG_TRG_SRC         0xA19C
#define REG_TRG_ACT         0xA1C9
#define REG_TRG_DLY_VAL     N1693
#define REG_TRG_DLY_MIN     N1199
#define REG_TRG_DLY_MAX     N1200
#define REG_TRG_EXE         0xA19E
#define REG_PKT_LEN         0xA2C3 // Stream payload length (N707)
#define REG_PIX_FMT         0xA493 // Pixcel Format (N1171)
#define REG_PIX_MSK         0xA49C
#define REG_LITSRC_SEL      N241
#define REG_ISP_EN          N319
#define REG_AWB_AUTO        N320
#define REG_AWB_COE         N321
#define REG_AWB_RED         N327
#define REG_AWB_GRE         N328
#define REG_AWB_BUE         N329
#define REG_AWB_MIN         N331
#define REG_AWB_MAX         N332
#define REG_TRI_SEL         N413
#define REG_FRM_CNT_VAL     N416
#define REG_FRM_CNT_MIN     N417
#define REG_FRM_CNT_MAX     N418
#define REG_FRM_CNT_INC     N419
#define REG_EXP_VAL         N472
#define REG_LINE_RATE_VAL   N477
#define REG_LINE_RATE_MIN   N478
#define REG_LINE_RATE_MAX   N479
#define REG_DEB_MAX         N549
#define REG_IO1_DEB         N552
#define REG_TRIGR_CNT_RST   N664
#define REG_FRAME_CNT_RST   N665
#define REG_USER_SET_CUR    N810
#define REG_USER_SET_SAVE   N813
#define REG_USER_SET_SEL    N824
#define REG_USER_SET_DEF    N826
#define REG_USER_SET_LOAD   N696
#define REG_CHUNK_EN        N984
#define REG_CHUNK_TIMESTAMP N990
#define REG_CHUNK_FRAME_CNT N992
#define REG_CHUNK_TRIGR_CNT N993
#define REG_ALG_GAIN        N108
#define REG_ALG_GAIN_MIN    N109
#define REG_ALG_GAIN_MAX    N110
#define REG_SCAN_TYPE       N950

/* Pixel format */
#define FMT_MONO8           0x01080001
#define FMT_BAYER_GR8       0x01080008
#define FMT_BAYER_RG8       0x01080009
#define FMT_BAYER_GB8       0x0108000a
#define FMT_BAYER_BG8       0x0108000b
#define FMT_RGB8_PACKED     0x02180014
#define FMT_YUV422_PACKED   0x0210001f

/* genIcam xml */
#define XML_FILE_NAME       "boq.xml"

#define NAME_PREFIX         "ATV-A"
#define VENDOR_NAME         "ATV"

struct gvcp_cmd_header {
    u8 cMsgKeyCode; // 0x42
    u8       cFlag; // 0x11 allow broadcast ack;ack required
    u16       wCmd; // discovery_cmd=2;FORCEIP_CMD = 4;READREG_CMD=0x80
    u16       wLen; // payload length
    u16     wReqID; // request id = 1;READREG id=12345
};

struct gvcp_ack_header {
    u16 wStatus; // success=0;
    u16    wAck; // discover_ack=3;forceip_ack=5;READREG_ACK=0x81
    u16    wLen;
    u16  wAckID;
};

struct gvcp_ack_payload{
	u32        dwSpecVer;
	u32        dwDevMode;
    u16           MacRes;
	u8            Mac[6];
	u32       dwSupIpSet;
	u32       dwCurIpSet;
    u32          curRes1;
    u32          curRes2;
    u32          curRes3;
	u32            CurIP;
    u32          subRes1;
    u32          subRes2;
    u32          subRes3;
	u32          SubMask;
    u32          gatRes1;
    u32          gatRes2;
    u32          gatRes3;
	u32          Gateway;
	char   szFacName[32];
	char szModelName[32];
	char    szDevVer[32];
	char   szFacInfo[48];
	char    szSerial[16];
	char  szUserName[16];
};

struct gvcp_discover_ack{
    struct gvcp_ack_header   header;
    struct gvcp_ack_payload payload;
};

struct gvcp_forceip_cmd{
    struct gvcp_cmd_header header;
    u16           MacRes;
    u8            Mac[6];
    u32          curRes1;
    u32          curRes2;
    u32          curRes3;
    u32            CurIP;
    u32          subRes1;
    u32          subRes2;
    u32          subRes3;
    u32          SubMask;
    u32          gatRes1;
    u32          gatRes2;
    u32          gatRes3;
    u32          Gateway;
};

struct gvcp_forceip_bas_cmd{
    struct gvcp_cmd_header header;
    u16           MacRes;
    u8            Mac[6];
    u32            setIP;
    u32          curRes1;
    u32          curRes2;
    u32          curRes3;
    u32            CurIP;
    u32          subRes1;
    u32          subRes2;
    u32          subRes3;
    u32          SubMask;
    u32          gatRes1;
    u32          gatRes2;
    u32          gatRes3;
    u32          Gateway;
    u8        UserID[16];
};

struct gvcp_packet_resend_payload{
    u16      streamChIdx;
    u16          blockId;
    u32       firstPktId;
    u32        lastPktId;
};

struct gvcp_packet_resend_cmd{
    struct gvcp_cmd_header header;
    struct gvcp_packet_resend_payload payload;
};

struct gvcp_readreg_cmd{
    struct gvcp_cmd_header header;
    u32 dwRegAddr[];
};

struct gvcp_readreg_ack{
    struct gvcp_ack_header header;
    u32 dwRegValue[];
};

struct gvcp_readmem_cmd {
    struct gvcp_cmd_header header;
    u32 dwMemAddr;
    u16 dwMemRes;
    u16 dwMemCount;
};

struct gvcp_readmem_ack {
    struct gvcp_ack_header header;
    u32 dwMemAddr;
    u8  pMemBuf[];
};

struct gvcp_writereg {
    u32  dwRegAddr;
    u32 dwRegValue;
};

struct gvcp_writereg_cmd {
    struct gvcp_cmd_header header;
    struct gvcp_writereg    reg[];
};

struct gvcp_writereg_ack {
    struct gvcp_ack_header header;
    u16                       res;
    u16                     index;
};

struct gvcp_writemem_cmd {
    struct gvcp_cmd_header header;
    u32 dwMemAddr;
    u8  pMemBuf[];
};

struct gvcp_writemem_ack {
    struct gvcp_ack_header header;
    u16                       res;
    u16                     index;
};

struct gvcp_xml_header {
    u32 magic;
    u32   crc;
    u32   len;
    u32   res;
};

enum GVCP_GAMMA_TYPE{
    GAMMA_USER = 1,
    GAMMR_SRGB = 2
};

enum GVCP_ACQ_MODE {
    ACQ_CONTINUOUS = 1,
    ACQ_SINGLE_FRAME,
    ACQ_MULTI_FRAME
};

enum GVCP_TRG_SRC {
    TRG_SOFTWARE,
    TRG_LINE1
};

typedef struct {
    u32        res:12;
    u32 yuv422Yuyv:1;
    u32 yuv422Pack:1;
    u32   bgr8Pack:1;
    u32   rgb8Pack:1;
    u32  bayerBG12:1;
    u32  bayerGB12:1;
    u32  bayerRG12:1;
    u32  bayerGR12:1;
    u32  bayerBG10:1;
    u32  bayerGB10:1;
    u32  bayerRG10:1;
    u32  bayerGR10:1;
    u32   bayerBG8:1;
    u32   bayerGB8:1;
    u32   bayerRG8:1;
    u32   bayerGR8:1;
    u32 mono12Pack:1;
    u32     mono12:1;
    u32     mono10:1;
    u32      mono8:1;
} GVCP_PIX_MASK_T;

typedef union {
    GVCP_PIX_MASK_T mask;
    u32 value;
} GVCP_PIX_MASK_REG_T;

//void sock_init(int* sockfd, struct sockaddr_in* Addr);

void gvcp_ack_discover(int iFd, char* m_szRemoteIp, u16 desPort, u16 wReqID);
void gvcp_ack_readreg(int sockfd, char* m_szRemoteIp, u16 desPort, void *req);
void gvcp_ack_writereg(int sockfd, char* m_szRemoteIp, u16 desPort, void *req);
void gvcp_ack_readmem(int sockfd, char* m_szRemoteIp, u16 desPort, void *req);
void gvcp_loop();

u32 gvcp_read_reg(u32 addr);
u32 gvcp_write_reg(u32 addr, u32 val);

bool gvcp_has_connect(void);

void gvcp_timeout(void);

bool gvcp_timeout_almost(void);

void gvcp_heart_check(u32 now);

void gvcp_heart_update(u32 time);

void gvcp_gamma_selector(enum GVCP_GAMMA_TYPE type);

void gvcp_gamma_enable(void);

void gvcp_gamma_disable(void);

void lwipGvcp_init(void);

#ifdef __cplusplus
}
#endif

#endif /* SRC_LWIPGVCP_H_ */
